#ifndef DIR_HPP
#define DIR_HPP

#include <sys/types.h>
#include <dirent.h>
#include <string>
#include <cerrno>
#include <cstdio>
#include <filesystem>

#ifndef PATH_MAX
#define PATH_MAX 1024
#endif

namespace sh
{
/**
 * 目录操作
 * @author: haitao.lin
 */
class Dir
{
public:
    /**
     * 获取当前工作目录
     */
    static std::string currentWorkPath()
    {
        char buf[PATH_MAX] = {0x00};
        if (nullptr == getcwd(buf, sizeof(buf) - 1))
        {
            return std::string();
        }
        return std::string(buf);
    }

    /**
     * 设置当前的工作目录
     */
    static bool setCurrentWorkPath(const std::string &path)
    {
        return chdir(path.c_str()) != -1;
    }

    /**
     * 目录或者文件是否存在
     */
    static bool exists(const std::string &path)
    {
        return access(path.c_str(), F_OK) == 0;
    }

    /**
     * 创建目录，支持创建多级目录
     */
    static bool mkdir(const std::string &path)
    {
        if (path.empty())
        {
            return false;
        }

        if (exists(path))
        {
            return true;
        }

        std::string dirPath = path;
        if (dirPath[dirPath.size() - 1] != '/')
        {
            dirPath += '/';
        }

        for (unsigned int i = 0; i < dirPath.size(); ++i)
        {
            if (dirPath[i] == '/')
            {
                if (i == 0)
                {
                    continue;
                }

                std::string tempPath = dirPath.substr(0, i);
                if (!exists(tempPath))
                {
                    if (::mkdir(tempPath.c_str()) == -1)
                    {
                        return false;
                    }
                }
            }
        }

        return true;
    }
    static bool remove(const std::string &path)
    {
        if (path.empty())
        {
            return false;
        }

        if (!exists(path))
        {
            return false;
        }

        int ret = std::remove(path.c_str());
        return -1 != ret;
    }

#ifdef UNIX
    static std::string currentExePath()
    {
        char buf[PATH_MAX] = {'\0'};

        int ret = readlink("/proc/self/exe", buf, PATH_MAX);
        if (ret < 0 || ret >= PATH_MAX)
        {
            return "";
        }

        std::string path(buf);
        int pos = path.find_last_of("/");
        if (pos == -1)
        {
            return "";
        }

        path = path.substr(0, pos);

        return path;
    }
#endif
};
}

#endif //DIR_HPP
